﻿using ControlzEx.Theming;
using DxfMonitor.Data;
using DxfMonitor.View;
using Microsoft.EntityFrameworkCore;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;

namespace DxfMonitor.ViewModel
{
    public class MainViewModel : ObservableObject
    {
        public static MainViewModel Main;

        public MainViewModel()
        {
            FolderPairViewModels = new ObservableCollection<FolderPairViewModel>(
                Repository.LoadAllDxfPairs().Select(x => new FolderPairViewModel(x)));
            foreach (FolderPairViewModel folderPairViewModel in FolderPairViewModels)
            {
                if (!folderPairViewModel.CanCheck && folderPairViewModel.IsChecked)
                {
                    folderPairViewModel.IsChecked = false;
                }
            }
            Main = this;

            // create accent color menu items for the demo
            this.AccentColors = ThemeManager.Current.Themes
                                            .GroupBy(x => x.ColorScheme)
                                            .OrderBy(a => a.Key)
                                            .Select(a => new AccentColorMenuData { Name = a.Key, ColorBrush = a.First().ShowcaseBrush })
                                            .ToList();

            // create metro theme color menu items for the demo
            this.AppThemes = ThemeManager.Current.Themes
                                         .GroupBy(x => x.BaseColorScheme)
                                         .Select(x => x.First())
                                         .Select(a => new AppThemeMenuData { Name = a.BaseColorScheme, BorderColorBrush = a.Resources["MahApps.Brushes.ThemeForeground"] as Brush, ColorBrush = a.Resources["MahApps.Brushes.ThemeBackground"] as Brush })
                                         .ToList();
            ExecuteRunCommand();
        }
        public List<AccentColorMenuData> AccentColors { get; set; }

        public List<AppThemeMenuData> AppThemes { get; set; }
        private ObservableCollection<FolderPairViewModel> folderPairViewModels;
        public ObservableCollection<FolderPairViewModel> FolderPairViewModels
        {
            get => folderPairViewModels;
            set => SetProperty(ref folderPairViewModels, value);
        }

        private FolderPairViewModel selectedPairViewModel;
        public FolderPairViewModel SelectedPairViewModel
        {
            get => selectedPairViewModel;
            set
            {
                SetProperty(ref selectedPairViewModel, value);
                Application.Current.Dispatcher.Invoke(() =>
                {
                    RunSelectedCommand.NotifyCanExecuteChanged();
                    MainWindow mainWindow = MainWindow.MainWin;
                    if (mainWindow != null)
                    {
                        mainWindow.BringFolderIntoView();
                    }
                });

            }
        }


        private bool autoUpdate;
        public bool AutoUpdate
        {
            get => autoUpdate;
            set => SetProperty(ref autoUpdate, value);
        }

        private RelayCommand runCommand;
        public RelayCommand RunCommand => runCommand ?? (runCommand = new RelayCommand(ExecuteRunCommand, CanExecuteRunCommand));

        private bool CanExecuteRunCommand()
        {
            return FolderPairViewModels.Any(x => x.IsChecked) && !IsRunning;
            //return false;
        }



        private bool isRunning;
        public bool IsRunning
        {
            get => isRunning;
            set => SetProperty(ref isRunning, value);
        }

        public int TotalChangedFolderPairsCount
        {
            get => this.FolderPairViewModels.Count(x => x.Added.Any() || x.Removed.Any());
        }

        private void ExecuteRunCommand()
        {
            if (!WarnUpdate())
            {
                return;
            }
            IsRunning = true;
            RunCommand.NotifyCanExecuteChanged();
            Task.Run(() =>
            {
                Repository.DeleteTooOld();
                foreach (FolderPairViewModel pairViewModel in FolderPairViewModels.Where(x => x.IsChecked))
                {
                    pairViewModel.CompareFiles(AutoUpdate);
                    //Thread.Sleep(3000);
                }
                OnPropertyChanged(nameof(TotalChangedFolderPairsCount));

                if (SelectedPairViewModel == null || !(SelectedPairViewModel.Added.Any() || SelectedPairViewModel.Removed.Any()))
                {
                    SelectedPairViewModel = FolderPairViewModels.OrderBy(x => x, new NaturalFolderPairViewModelGenericSorter()).FirstOrDefault(x => x.Added.Any() || x.Removed.Any());
                }

                AutoUpdate = false;
                IsRunning = false;
                Application.Current.Dispatcher.BeginInvoke((Action)delegate
                {
                    RunCommand.NotifyCanExecuteChanged();
                });
            });
        }



        ///

        private RelayCommand runSelectedCommand;
        public RelayCommand RunSelectedCommand => runSelectedCommand ?? (runSelectedCommand = new RelayCommand(ExecuteRunSelectedCommand, CanExecuteRunSelectedCommand));

        private bool CanExecuteRunSelectedCommand()
        {
            return SelectedPairViewModel != null
                && SelectedPairViewModel.CanCheck
                && !IsRunSelectedning;
        }


        private bool isRunSelectedning;
        public bool IsRunSelectedning
        {
            get => isRunSelectedning;
            set => SetProperty(ref isRunSelectedning, value);
        }

        private bool WarnUpdate()
        {
            if (AutoUpdate &&
           (MessageBox.Show("是否确认更新?", "警告", MessageBoxButton.OKCancel)
           == MessageBoxResult.Cancel))
            {
                return false;
            }

            return true;
        }

        private void ExecuteRunSelectedCommand()
        {
            IsRunSelectedning = true;
            RunSelectedCommand.NotifyCanExecuteChanged();
            Task.Run(() =>
            {
                Repository.SavePairAndFolder(SelectedPairViewModel);
                SelectedPairViewModel.CompareFiles(AutoUpdate);
                OnPropertyChanged(nameof(TotalChangedFolderPairsCount));
                AutoUpdate = false;
                IsRunSelectedning = false;
                Application.Current.Dispatcher.BeginInvoke((Action)delegate
                {
                    RunSelectedCommand.NotifyCanExecuteChanged();
                });
            });
        }
    }
}
